package com.xishu.service.print;

import com.xishu.bo.DetailReport;
import com.xishu.bo.printer.PrinterItem;
import com.xishu.bo.printer.PrinterLine;
import com.xishu.client.PrinterClient;
import com.xishu.config.Config;
import com.xishu.config.Constant;
import com.xishu.entity.Company;
import com.xishu.entity.hardware.Printer;
import com.xishu.entity.order.Order;
import com.xishu.entity.shop.PayType;
import com.xishu.entity.shop.Shop;
import com.xishu.response.ResponseStatus;
import com.xishu.response.VerifyUtil;
import com.xishu.service.*;
import com.xishu.service.order.base.OrderService;
import com.xishu.util.AES;
import com.xishu.util.BigDecimalUtil;
import com.xishu.util.DateUtil;
import com.xishu.util.Tools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import static com.xishu.config.Constant.*;

public class CloseReportPrintService implements Tools {
    private static CloseReportPrintService instance = new CloseReportPrintService();
    private static Logger logger = LoggerFactory.getLogger(CloseReportPrintService.class);
    private CommonService commonService = CommonService.getInstance();
    private PrinterClient printerClient = PrinterClient.getInstance();
    private OrderService orderService = OrderService.getInstance();
    private CompanyService companyService = CompanyService.getInstance();
    private LangService langService = LangService.getInstance();
    private PayTypeService payTypeService = PayTypeService.getInstance();

    public static final int LINE_LENGTH = 48;
    public static final int ONE_ITEM_LENGTH = LINE_LENGTH / 3;
    private Config config = Config.getInstance();

    private CloseReportPrintService() {
    }

    public static CloseReportPrintService getInstance() {
        return instance;
    }

    /**
     * 打印新版本的闭店报告
     *
     * @param shopId
     * @param printerId
     * @param touchDeviceUuid
     * @return
     */
    public boolean printCloseReport(Long shopId, Long printerId, String touchDeviceUuid, DetailReport detailReport) throws Exception {
        Shop shop = ShopService.getInstance().findShopById(shopId);
        Company company = companyService.findCompanyById(shop.getCompanyId());
        Printer barCounterPrinter = commonService.findEntity(printerId, Printer.class);
        boolean zh = commonService.isZh(barCounterPrinter.getLang());

        VerifyUtil.verify(() -> barCounterPrinter != null, ResponseStatus.BAR_COUNTER_PRINTER_NOT_CONFIG);
        String printerSn = AES.decrypt(barCounterPrinter.getPrinterSn());

        //生成打印字符串
        ArrayList<PrinterLine> printerLines = new ArrayList<>();

        //打印机的LOGO
        printerLines.add(printerClient.newLogo());

        if (isNotEmpty(company.getPrintCompanyName())) {
            //公司名称
            printerLines.add(printerClient.newLine(company.getPrintCompanyName(), true, true));
        } else {
            printerLines.add(printerClient.newLine(companyService.getCompanyName(company, zh), true, true));
        }
        //餐厅名称
        printerLines.add(printerClient.newLine("(" + langService.getShopName(shop, zh) + ")", true, null));

        //餐厅地址
        printerLines.addAll(CommonPrintService.getInstance().getShopAddressLine(shop, zh));

        //餐厅电话
        if (isNotEmpty(shop.getPhone())) {
            printerLines.add(printerClient.newLine(config.label_phone(zh) + getString(shop.getPhone()), null, null));
        }

        //日期
        if (getBoolean(shop.getBusinessStatus())){
            printerLines.add(printerClient.newLine(config.label_date(zh) + DateUtil.formatDateMin(shop.getOpenTime()) + " - " + DateUtil.formatDateMin(System.currentTimeMillis()), null, null));
        }else {
            printerLines.add(printerClient.newLine(config.label_date(zh) + DateUtil.formatDateMin(shop.getOpenTime()) + " - " + DateUtil.formatDateMin(shop.getCloseTime()), null, null));

        }

        //分隔符
        printerLines.add(printerClient.printSeparator());

        //支付方式标题
        printerLines.add(addPayTypeLine(zh));

        /*************支付方式***********************/
        List<PrinterLine> payTypeLineList = addPayTypeCash(zh, shopId);
        /***********支付方式***********************/

        //每一个支付方式的金额
        printerLines.addAll(payTypeLineList);
//        //添加外卖平台
//        printerLines.add(addTakeOutPlat(zh, shopId));
        //分隔符
        printerLines.add(printerClient.printSeparator());
        //总销售额
        printerLines.add(addTotalCash(zh, shopId));

        //如果是美国版本，添加含税的说明
        addLines(printerLines, taxDescription(zh));

        //分隔符
        printerLines.add(printerClient.printSeparator());

        //添加服务费
        PrinterLine serviceFeePrinterLine = addServiceFee(zh, shopId);

        if (serviceFeePrinterLine != null) {
            printerLines.add(serviceFeePrinterLine);
        }

        //添加小费
        if (Config.getInstance().isUsVersion()) {
            addLines(printerLines, addTips(zh, shop));
        }

        //美国版本，添加消费税
        if (Config.getInstance().isUsVersion()) {
            printerLines.add(addConsumptionTax(zh, shop));
        }

        //添加餐盒费
        printerLines.add(addPackageFee(zh, shopId));
        //添加外卖折扣
        printerLines.add(addTakeOutFee(zh, shopId));
        //添加优惠卷信息
        printerLines.add(addDiscountFee(zh, shopId));
        //分隔符
        printerLines.add(printerClient.printSeparator());

        //未支付
        printerLines.add(addUnpaid(zh, shopId));
        //已退款
        printerLines.add(addReturnCash(zh, shopId));

        //空一行
        printerLines.add(printerClient.emptyLine());

        //添加客流量订单
        printerLines.add(addDinners(zh, shopId));
        //添加订单量
        printerLines.add(addOrderNumber(zh, shopId));
        //添加删除订单量
        printerLines.add(addDeleteOrderNumber(zh, shopId));
        //添加删除菜品
        printerLines.add(addDeleteOrderItemNumber(zh, shopId));
        //餐厅堂食
        printerLines.add(addTangShiOrderNumber(zh, shopId));
        //添加外卖订单数量
        printerLines.add(addTakeOutOrderNumber(zh, shopId));

        //添加外卖平台订单数量
        printerLines.add(addTakeOutPlatOrderNumber(zh, shopId));

        //空一行
        printerLines.add(printerClient.emptyLine());
        //空一行
        printerLines.add(printerClient.emptyLine());

        /*****************会员系统里面的相关数据打印************/
        //如果开启了会员系统，那么打印会员报告
        if (company.getCompanyConfig().getCustomerOpen()) {
            printerLines.addAll(addCustomerReport(shop, zh));
        }
        /*****************会员系统里面的相关数据打印************/

        //美国版本，打印净营收
        if (config.isUsVersion()) {
            printerLines.add(addNetSale(shop, zh));
            //添加新的一行提示
            printerLines.add(printerClient.newLine(config.close_report_without_tax(zh)));
            //添加分隔线
            printerLines.add(printerClient.printSeparator());

            //添加含税说明
            printerLines.add(addNetSaleWithTax(shop, zh));
            //添加新的一行提示
            printerLines.add(printerClient.newLine(config.close_report_with_tax(zh)));
            //添加分隔线
            printerLines.add(printerClient.printSeparator());
        }

        //添加两个空行
        printerLines.add(printerClient.emptyLine());
        printerLines.add(printerClient.emptyLine());

        /***只有详细报告才需要打印***/
        if (detailReport != null) {
            //每一条详细的记录
            List<Order> orderList = ReportService.getInstance().payedSubOrderList(shopId);
            orderList = filterCloseOrderList(orderList, detailReport);

            //计算小费金额
            double tipsSum = orderList.stream().mapToDouble(p -> getDouble(p.getTipsFee())).sum();

            boolean canShowTipsTitle = false;
            if (Config.getInstance().isUsVersion() && getBoolean(shop.getShopConfig().getTips())) {
                logger.info("show tips title");
                canShowTipsTitle = true;
            } else if (tipsSum != 0d) {
                logger.info("show tips title");
                //有小费，则显示
                canShowTipsTitle = true;
            }

            /****添加详细报告***/
            printerLines.add(addDetailReportTitle(zh));

            //添加详情报告小标题
            printerLines.add(addDetailReportSubTitle(zh, canShowTipsTitle));

            printerLines.addAll(addDetailReportList(zh, orderList, canShowTipsTitle));
            //分隔符
            printerLines.add(printerClient.printSeparator());
            //添加订单总的记录
            printerLines.add(addDetailReportTotal(orderList, canShowTipsTitle));
        }

        return printerClient.printList(printerLines, printerSn, printerId);
    }


    /**
     * 添加支付入口
     *
     * @return
     */
    private PrinterLine addPayTypeLine(Boolean zh) {
        PrinterLine printerLine = new PrinterLine();
        printerLine.setDirect(true);
        PrinterItem printerItem = new PrinterItem();
        StringBuilder stringBuilder = new StringBuilder();

        //点16个位，支付方式
        String payType = config.close_report_pay_type(zh);
        stringBuilder.append(printerClient.centerLength(payType, LINE_LENGTH / 4));

        //点16个位，堂食
        String tang_shi = config.close_report_tang_shi(zh);
        stringBuilder.append(printerClient.centerLength(tang_shi, LINE_LENGTH / 4));

        //点16个位，外卖
        String take_out = config.close_report_take_out(zh);
        stringBuilder.append(printerClient.centerLength(take_out, LINE_LENGTH / 4));

        //点16个位，总额
        String total = config.close_report_total(zh);
        stringBuilder.append(printerClient.centerLength(total, LINE_LENGTH / 4));
        printerItem.setContent(stringBuilder.toString());
        printerLine.add(printerItem);

        return printerLine;
    }

    /**
     * 添加每一种支付方式
     *
     * @param zh
     * @return
     */
    private List<PrinterLine> addPayTypeCash(Boolean zh, Long shopId) throws Exception {
        zh = zh == null || zh;
        List<PrinterLine> printerLines = new ArrayList<>();
        List<Integer> orderPayTypeList = null;
        List<PayType> payTypeList = payTypeService.findPayTypeListCache_Stripe(shopId);

        orderPayTypeList = payTypeList.stream().map(payType -> payType.getType()).collect(Collectors.toList());

        for (Integer payType : orderPayTypeList) {
            PrinterLine printerLine = new PrinterLine();
            printerLine.setDirect(true);
            PrinterItem printerItem = new PrinterItem();
            printerLine.add(printerItem);

            //开始添加内容
            StringBuffer sb = new StringBuffer();
            PayType payTypeEntity = payTypeService.filterPayType(payTypeList, payType);
            sb.append(printerClient.appendSpace(payTypeService.getPayTypeName(payTypeEntity, zh), LINE_LENGTH / 4));

            //添加堂食金额
            Double tangShiCash = ReportService.getInstance().sumTangShiCash(shopId, payType);
            sb.append(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(showMoneyDouble(tangShiCash))), LINE_LENGTH / 4));

            //添加外卖金额
            Double takeOutCash = ReportService.getInstance().sumTakeOutCash(shopId, payType);
            sb.append(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(showMoneyDouble(takeOutCash))), LINE_LENGTH / 4));

            //总额
            Double total = ReportService.getInstance().sumCash(shopId, payType);
            sb.append(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(showMoneyDouble(total))), LINE_LENGTH / 4));

            printerItem.setContent(sb.toString());
            printerLines.add(printerLine);
        }

        return printerLines;
    }

    /**
     * 添加总的销售额
     *
     * @param zh
     * @param shopId
     * @return
     */
    private PrinterLine addTotalCash(Boolean zh, Long shopId) throws Exception {
        PrinterLine printerLine = printerClient.newLine();
        PrinterItem printerItem = printerLine.getPrinterItem();
        StringBuffer sb = new StringBuffer();

        //添加标题
        String totalSaleTitle = printerClient.appendSpace(config.close_report_total_sale(zh), LINE_LENGTH / 8);
        sb.append(printerClient.appendDouble(totalSaleTitle));

        //添加堂食销售额
        List<Integer> orderPayTypeList = payTypeService.findPayTypeListCache_Stripe(shopId).stream().map(payType -> payType.getType()).collect(Collectors.toList());

        double tangShiTotalSale = orderPayTypeList.stream().mapToDouble(payType -> {
            try {
                return ReportService.getInstance().sumTangShiCash(shopId, payType);
            } catch (Exception e) {
                logger.error("e");
                return 0d;
            }
        }).sum();
        //加粗居中
        sb.append(printerClient.appendBold(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(showMoneyDouble(tangShiTotalSale))), LINE_LENGTH / 4)));

        //添加外卖销售额
        double takeOutTotalSale = orderPayTypeList.stream().mapToDouble(payType -> {
            try {
                return ReportService.getInstance().sumTakeOutCash(shopId, payType);
            } catch (Exception e) {
                logger.error("e");
                return 0d;
            }
        }).sum();
        //加粗居中
        sb.append(printerClient.appendBold(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(showMoneyDouble(takeOutTotalSale))), LINE_LENGTH / 4)));

        //总销售额
        double totalSale = orderPayTypeList.stream().mapToDouble(payType -> {
            try {
                return ReportService.getInstance().sumCash(shopId, payType);
            } catch (Exception e) {
                logger.error("e");
                return 0d;
            }
        }).sum();
        //加粗居中
        sb.append(printerClient.appendBold(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(showMoneyDouble(totalSale))), LINE_LENGTH / 4)));

        printerItem.setContent(sb.toString());
        return printerLine;
    }

    /**
     * 添加打印行
     *
     * @param lines
     * @param printerLine
     */
    public void addLines(List<PrinterLine> lines, PrinterLine printerLine) {
        if (printerLine == null) {
            return;
        }

        lines.add(printerLine);
    }

    /**
     * 含税说明
     *
     * @param zh
     * @return
     */
    private PrinterLine taxDescription(Boolean zh) {
        if (!config.isUsVersion()) {
            return null;
        }

        PrinterLine printerLine = printerClient.newLine();
        PrinterItem printerItem = printerLine.getPrinterItem();
        printerItem.setContent(config.close_report_has_tax(zh));
        return printerLine;
    }

    /**
     * 添加服务费
     *
     * @param zh
     * @param shopId
     * @return
     */
    private PrinterLine addServiceFee(Boolean zh, Long shopId) throws Exception {
        PrinterLine printerLine = printerClient.newLine();
        PrinterItem printerItem = printerLine.getPrinterItem();
        StringBuffer sb = new StringBuffer();

        //添加服务费标题
        String serviceFeeTitle = config.close_report_service_fee(zh);
        //只加标题了
        sb.append(printerClient.appendSpace(serviceFeeTitle, LINE_LENGTH / 4 * 3));

        //添加真实的服务费
        Double serviceFee = showMoneyDouble(ReportService.getInstance().sumServiceFee(shopId));
        //如果是美国版本，服务费为0，则不显示
        if (Config.getInstance().isUsVersion() && serviceFee == 0d) {
            return null;
        }

        sb.append(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(serviceFee)), LINE_LENGTH / 4));

        printerItem.setContent(sb.toString());
        return printerLine;
    }

    /**
     * 添加小费
     *
     * @param zh
     * @param shop
     * @return
     * @throws Exception
     */
    private PrinterLine addTips(Boolean zh, Shop shop) throws Exception {
        Long shopId = shop.getId();
        StringBuffer sb = new StringBuffer();
        //添加标题
        String tipsFeeTitle = config.close_tips_fee(zh);
        sb.append(printerClient.appendSpace(tipsFeeTitle, LINE_LENGTH / 4 * 3));

        //添加小费
        Double tips = showMoneyDouble(ReportService.getInstance().sumTipsFee(shopId));
        logger.info("tips is {}", tips);

        //没有开小费，并且小费金额是0，不显示
        if (!getBoolean(shop.getShopConfig().getTips()) && tips == 0d) {
            return null;
        }

        sb.append(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(tips)), LINE_LENGTH / 4));

        return printerClient.newLine(sb.toString());
    }

    /**
     * 添加消费税
     *
     * @param zh
     * @param shop
     * @return
     */
    private PrinterLine addConsumptionTax(Boolean zh, Shop shop) throws Exception {
        StringBuffer sb = new StringBuffer();
        //添加标题
        String packageFeeTitle = config.string_consumptionTax_fee(zh);
        packageFeeTitle = String.format(packageFeeTitle, showMoneyDouble(shop.getShopConfig().getConsumptionTax()));
        sb.append(printerClient.appendSpace(packageFeeTitle, LINE_LENGTH / 4 * 3));

        //添加餐盒费
        Double consumptionFee = showMoneyDouble(ReportService.getInstance().sumConsumptionTax(shop.getId()));
        sb.append(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(consumptionFee)), LINE_LENGTH / 4));

        return printerClient.newLine(sb.toString());
    }

    /**
     * 添加包装费
     *
     * @param zh
     * @param shopId
     * @return
     */
    private PrinterLine addPackageFee(Boolean zh, Long shopId) throws Exception {
        StringBuffer sb = new StringBuffer();
        //添加标题
        String packageFeeTitle = config.close_report_package_fee(zh);
        sb.append(printerClient.appendSpace(packageFeeTitle, LINE_LENGTH / 4 * 3));

        //添加餐盒费
        Double packageFee = showMoneyDouble(ReportService.getInstance().sumPackageFee(shopId));
        sb.append(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(packageFee)), LINE_LENGTH / 4));

        return printerClient.newLine(sb.toString());
    }


    /**
     * 添加外卖的折扣部分
     *
     * @param zh
     * @param shopId
     * @return
     * @throws Exception
     */
    private PrinterLine addTakeOutFee(Boolean zh, Long shopId) throws Exception {
        Shop shop = ShopService.getInstance().findShopById(shopId);
        StringBuffer sb = new StringBuffer();
        //添加标题
        String takeOutFeeTitle = config.close_report_take_out_fee(zh);

//        if (zh == null || getBoolean(zh)) {
//            Double takeFeePercent = getDouble(shop.getTakeoutFeePercent());
//            //整数打折
//            if (new BigDecimal(showMoneyDouble(takeFeePercent)).equals(new BigDecimal(showMoneyDouble(takeFeePercent).intValue()))) {
//                takeOutFeeTitle = takeOutFeeTitle + String.format("(%s折)", getDouble(shop.getTakeoutFeePercent()).intValue());
//            } else {
//                //几点几折
//                takeOutFeeTitle = takeOutFeeTitle + String.format("(%s折)", showMoneyDouble(shop.getTakeoutFeePercent()));
//            }
//        } else {
//            Double takeFeePercent = getDouble(shop.getTakeoutFeePercent());
//            int takeFeePercentInt = getDouble(takeFeePercent * 10).intValue();
//            takeOutFeeTitle = takeOutFeeTitle + String.format("(%s%%)", takeFeePercentInt);
//        }

        sb.append(printerClient.appendSpace(takeOutFeeTitle, LINE_LENGTH / 4 * 3));
        Double takeOutDiscountFee = showMoneyDouble(ReportService.getInstance().sumTakeOutDiscount(shopId));

        sb.append(printerClient.centerLength("-" + BigDecimalUtil.format(BigDecimal.valueOf(takeOutDiscountFee)), LINE_LENGTH / 4));

        return printerClient.newLine(sb.toString());
    }

    /**
     * 添加优惠卷
     *
     * @param zh
     * @param shopId
     * @return
     */
    private PrinterLine addDiscountFee(Boolean zh, Long shopId) throws Exception {
        StringBuffer sb = new StringBuffer();
        sb.append(printerClient.appendSpace(config.close_report_ticket_fee(zh), LINE_LENGTH / 4 * 3));
        Double discountFee = showMoneyDouble(ReportService.getInstance().sumDiscountFee(shopId));

        sb.append(printerClient.centerLength("-" + BigDecimalUtil.format(BigDecimal.valueOf(discountFee)), LINE_LENGTH / 4));

        return printerClient.newLine(sb.toString());
    }

    /**
     * 未支付订单
     *
     * @param zh
     * @param shopId
     * @return
     */
    private PrinterLine addUnpaid(Boolean zh, Long shopId) throws Exception {
        StringBuffer sb = new StringBuffer();
        String unpaidTitle = config.close_report_unpaid(zh);
        sb.append(printerClient.appendSpace(unpaidTitle, LINE_LENGTH / 4));

        ReportService reportService = ReportService.getInstance();
        double tangShiUnpaid = showMoneyDouble(reportService.countSendToKitchenUnpaidForTangShi(shopId));
        sb.append(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(tangShiUnpaid)), LINE_LENGTH / 4));

        double takeOutUnpaid = showMoneyDouble(reportService.sumSendToKitchenUnpaidForTakeOut(shopId));
        sb.append(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(takeOutUnpaid)), LINE_LENGTH / 4));

        Double unpaid = showMoneyDouble(reportService.countSendToKitchenUnpaid(shopId));
        sb.append(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(unpaid)), LINE_LENGTH / 4));


        return printerClient.newLine(sb.toString());
    }

    /**
     * 添加已退款
     *
     * @param zh
     * @param shopId
     * @return
     */
    private PrinterLine addReturnCash(Boolean zh, Long shopId) throws Exception {
        StringBuffer sb = new StringBuffer();
        String returnCashTitle = config.close_report_return_cash(zh);
        sb.append(printerClient.appendSpace(returnCashTitle, LINE_LENGTH / 4));

        ReportService reportService = ReportService.getInstance();
        double tangShiReturnCash = showMoneyDouble(reportService.returnCashForTangShi(shopId));
        sb.append(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(tangShiReturnCash)), LINE_LENGTH / 4));

        double takeOutReturnCash = showMoneyDouble(reportService.returnCashForTakeOut(shopId));
        sb.append(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(takeOutReturnCash)), LINE_LENGTH / 4));

        Double returnCash = showMoneyDouble(reportService.returnCash(shopId));
        sb.append(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(returnCash)), LINE_LENGTH / 4));

        return printerClient.newLine(sb.toString());
    }

    /**
     * 添加客流量
     *
     * @param zh
     * @param shopId
     * @return
     * @throws Exception
     */
    private PrinterLine addDinners(Boolean zh, Long shopId) throws Exception {
        StringBuffer sb = new StringBuffer();

        //添加标题
        sb.append(printerClient.appendSeparator(config.close_report_dinners(zh), LINE_LENGTH / 4 * 3, "-"));
        //添加人数
        ReportService reportService = ReportService.getInstance();
        int dinners = getInt(reportService.dinners(shopId));

        String dinnerString = null;
        if (zh == null || zh) {
            dinnerString = BigDecimalUtil.format(BigDecimal.valueOf(dinners)) + "人";
        } else {
            dinnerString = BigDecimalUtil.format(BigDecimal.valueOf(dinners)) + " People";
        }

        sb.append(dinnerString);

        return printerClient.newLine(sb.toString());
    }


    /**
     * 添加订单量
     *
     * @param zh
     * @param shopId
     * @return
     */
    private PrinterLine addOrderNumber(Boolean zh, Long shopId) throws Exception {
        StringBuffer sb = new StringBuffer();
        //添加标题
        sb.append(printerClient.appendSeparator(config.close_report_order_number(zh), LINE_LENGTH / 4 * 3, "-"));
        //添加订单量
        ReportService reportService = ReportService.getInstance();
        int orderNumber = getInt(reportService.orderNumber(shopId));

        String orderNumberString = null;
        if (zh == null || zh) {
            orderNumberString = BigDecimalUtil.format(BigDecimal.valueOf(orderNumber)) + "單";
        } else {
            orderNumberString = BigDecimalUtil.format(BigDecimal.valueOf(orderNumber)) + " Checks";
        }

        sb.append(orderNumberString);

        return printerClient.newLine(sb.toString());
    }

    /**
     * 添加删除订单量
     *
     * @param zh
     * @param shopId
     * @return
     */
    private PrinterLine addDeleteOrderNumber(Boolean zh, Long shopId) throws Exception {
        StringBuffer sb = new StringBuffer();
        //添加标题
        sb.append(printerClient.appendSeparator(config.close_report_delete_order_number(zh), LINE_LENGTH / 4 * 3, "-"));
        //添加订单量
        ReportService reportService = ReportService.getInstance();
        int deleteOrderNumber = reportService.deleteOrderNumber(shopId);

        String deleteOrderNumberString = null;
        if (zh == null || zh) {
            deleteOrderNumberString = BigDecimalUtil.format(BigDecimal.valueOf(deleteOrderNumber)) + "單";
        } else {
            deleteOrderNumberString = BigDecimalUtil.format(BigDecimal.valueOf(deleteOrderNumber)) + " Checks";
        }

        sb.append(deleteOrderNumberString);

        return printerClient.newLine(sb.toString());
    }

    /**
     * 添加删除订单菜品
     *
     * @param zh
     * @param shopId
     * @return
     */
    private PrinterLine addDeleteOrderItemNumber(Boolean zh, Long shopId) throws Exception {
        StringBuffer sb = new StringBuffer();
        //添加标题
        sb.append(printerClient.appendSeparator(config.close_report_delete_order_item_number(zh), LINE_LENGTH / 4 * 3, "-"));
        //添加订单量
        ReportService reportService = ReportService.getInstance();
        int deleteOrderItemNumber = reportService.deleteOrderItemNumber(shopId);

        String deleteOrderItemNumberString = null;
        if (zh == null || zh) {
            deleteOrderItemNumberString = deleteOrderItemNumber + "個";
        } else {
            deleteOrderItemNumberString = deleteOrderItemNumber + " Dishes";
        }

        sb.append(deleteOrderItemNumberString);

        return printerClient.newLine(sb.toString());
    }

    /**
     * 添加堂食订单数量
     *
     * @param zh
     * @param shopId
     * @return
     */
    private PrinterLine addTangShiOrderNumber(Boolean zh, Long shopId) throws Exception {
        StringBuffer sb = new StringBuffer();
        //添加标题
        sb.append(printerClient.appendSeparator(config.close_report_tang_shi_order_number(zh), LINE_LENGTH / 4 * 3, "-"));
        //添加订单量
        ReportService reportService = ReportService.getInstance();
        int tangShiOrderNumber = getInt(reportService.tangShiOrderNumber(shopId));

        String tangShiOrderNumberString = null;
        if (zh == null || zh) {
            tangShiOrderNumberString = BigDecimalUtil.format(BigDecimal.valueOf(tangShiOrderNumber)) + "單";
        } else {
            tangShiOrderNumberString = BigDecimalUtil.format(BigDecimal.valueOf(tangShiOrderNumber)) + " Checks";
        }

        sb.append(tangShiOrderNumberString);

        return printerClient.newLine(sb.toString());
    }

    /**
     * 添加外卖订单数量
     *
     * @param zh
     * @param shopId
     * @return
     */
    private PrinterLine addTakeOutOrderNumber(Boolean zh, Long shopId) throws Exception {
        StringBuffer sb = new StringBuffer();
        //添加标题
        sb.append(printerClient.appendSeparator(config.close_report_take_out_order_number(zh), LINE_LENGTH / 4 * 3, "-"));
        //添加订单量
        ReportService reportService = ReportService.getInstance();
        int takeOutOrderNumber = getInt(reportService.takeOutOrderNumber(shopId));

        String takeOutOrderNumberString = null;
        if (zh == null || zh) {
            takeOutOrderNumberString = BigDecimalUtil.format(BigDecimal.valueOf(takeOutOrderNumber)) + "單";
        } else {
            takeOutOrderNumberString = BigDecimalUtil.format(BigDecimal.valueOf(takeOutOrderNumber)) + " Checks";
        }

        sb.append(takeOutOrderNumberString);

        return printerClient.newLine(sb.toString());
    }

    /**
     * 添加会员系统的打印
     *
     * @param shop
     */
    public List<PrinterLine> addCustomerReport(Shop shop, Boolean zh) throws Exception {
        List<PrinterLine> printerLineList = new ArrayList<>();
        printerLineList.add(printerClient.printSeparator());
        printerLineList.add(addCustomerReportTitle(zh));
        printerLineList.add(addCustomerReportSubTitle(zh));

        //添加真實的支付費用
        printerLineList.addAll(addPayType_customer(shop.id, zh));
        printerLineList.add(printerClient.printSeparator());

        return printerLineList;
    }

    /**
     * 添加详情报告
     *
     * @param zh
     * @return
     */
    private PrinterLine addCustomerReportTitle(Boolean zh) {
        StringBuffer sb = new StringBuffer();
        sb.append(printerClient.appendCenter(printerClient.appendDouble(config.close_customer_report_title(zh))));
        return printerClient.newLine(sb.toString());
    }

    /**
     * 添加详情报告小标题
     *
     * @param zh
     * @return
     */
    private PrinterLine addCustomerReportSubTitle(Boolean zh) {
        StringBuffer sb = new StringBuffer();
        //单号
        sb.append(printerClient.centerLength(config.close_report_pay_type_title(zh), LINE_LENGTH / 4));
        //支付方式
        sb.append(printerClient.centerLength(config.customer_report_vip_title(zh), LINE_LENGTH / 2));
        //金额
        sb.append(printerClient.centerLength(config.customer_report_vip_sale_title(zh), LINE_LENGTH / 4));
        return printerClient.newLine(sb.toString());
    }

    /**
     * 添加每一种支付方式
     *
     * @param zh
     * @return
     */
    private List<PrinterLine> addPayType_customer(Long shopId, Boolean zh) throws Exception {
        List<PrinterLine> printerLines = new ArrayList<>();
        List<PayType> payTypeEntityList = payTypeService.findPayTypeListCache_Stripe(shopId);
        List<Integer> orderPayTypeList = payTypeEntityList.stream().map(payType -> payType.getType()).collect(Collectors.toList());

        ReportService reportService = ReportService.getInstance();
        Shop shop = ShopService.getInstance().findShopById(shopId);
        List<PrinterService.PrintPayType> payTypeList = new ArrayList<>();

        for (Integer payType : orderPayTypeList) {
            PrinterService.PrintPayType printPayType = new PrinterService.PrintPayType();
            printPayType.payType = payType;
            printPayType.vipFee = reportService.sumVip(shop, payType);
            double otherFee = reportService.sumCash(shopId, payType);
            printPayType.vipFeeAndOther = printPayType.vipFee + otherFee;
            payTypeList.add(printPayType);
        }

        //依次添加
        for (PrinterService.PrintPayType printPayType : payTypeList) {
            StringBuffer sb = new StringBuffer();
            int payType = printPayType.payType;
            PayType payTypeEntity = payTypeService.filterPayType(payTypeEntityList, payType);
            sb.append(printerClient.appendSpace(payTypeService.getPayTypeName(payTypeEntity, zh), LINE_LENGTH / 4));
            sb.append(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(printPayType.vipFee)), LINE_LENGTH / 2));
            sb.append(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(printPayType.vipFeeAndOther)), LINE_LENGTH / 4));
            PrinterLine printerLine = printerClient.newLine(sb.toString());
            printerLines.add(printerLine);
        }

        //添加总计
        {
            printerLines.add(printerClient.printSeparator());
            StringBuffer sb = new StringBuffer();
            sb.append(printerClient.appendDouble(printerClient.appendSpace(config.customer_report_vip_total_title(zh), LINE_LENGTH / 8)));
            sb.append(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(showMoneyDouble(payTypeList.stream().mapToDouble(p -> getDouble(p.vipFee)).sum()))), LINE_LENGTH / 2));
            sb.append(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(showMoneyDouble(payTypeList.stream().mapToDouble(p -> getDouble(p.vipFeeAndOther)).sum()))), LINE_LENGTH / 4));
            PrinterLine printerLine = printerClient.newLine(sb.toString());
            printerLines.add(printerLine);
        }

        return printerLines;
    }

    /**
     * 添加净营收
     *
     * @param shop
     * @param zh
     */
    public PrinterLine addNetSale(Shop shop, Boolean zh) {
        Double netSale = ReportService.getInstance().sumNetSale(shop);

        return printerClient.newTwoItemLine(config.close_report_net_sale(zh), BigDecimalUtil.format(BigDecimal.valueOf(netSale)), true, true);
    }

    public PrinterLine addNetSaleWithTax(Shop shop, Boolean zh) {
        Double netSale = ReportService.getInstance().sumNetSaleWithTax(shop);

        return printerClient.newTwoItemLine(config.close_report_net_sale_with_tax(zh), BigDecimalUtil.format(BigDecimal.valueOf(netSale)), true, true);
    }

    /**
     * 按照前端的过滤条件来处理
     *
     * @param orderList
     * @param detailReport
     * @return
     */
    private List<Order> filterCloseOrderList(List<Order> orderList, DetailReport detailReport) {
        getList(orderList).sort(new Comparator<Order>() {
            @Override
            public int compare(Order o1, Order o2) {
                if (o1.getOrderNo() < o2.getOrderNo()) {
                    return -1;
                } else if (o1.getOrderNo() > o2.getOrderNo()) {
                    return 1;
                } else {
                    //订单号相同，按照子订单号来排序
                    if (getInt(o1.getSubOrderId()) < getInt(o2.getSubOrderId())) {
                        return -1;
                    } else if (getInt(o1.getSubOrderId()) > getInt(o2.getSubOrderId())) {
                        return 1;
                    } else {
                        return 0;
                    }
                }

            }
        });

        //按照条件来过滤显示
        List<Integer> orderTypeList = new ArrayList<>();
        if (detailReport.isTakeout()) {
            orderTypeList.add(ORDER_TYPE_TAKE_OUT);
        }

        if (detailReport.isTangshi()) {
            orderTypeList.add(ORDER_TYPE_TANG_SHI);
            orderTypeList.add(ORDER_TYPE_QUICK_FOOD);
        }

        if (detailReport.isTakeoutPlat()) {
            orderTypeList.add(ORDER_TYPE_TAKE_OUT_PLAT);
        }

        //一个都没有，那么添加所有的
        if (isEmpty(orderTypeList)) {
            orderTypeList.add(ORDER_TYPE_TAKE_OUT);
            orderTypeList.add(ORDER_TYPE_TANG_SHI);
            orderTypeList.add(ORDER_TYPE_QUICK_FOOD);
            orderTypeList.add(ORDER_TYPE_TAKE_OUT_PLAT);
        }

        //处理支付方式
        List<Integer> payTypeList = getShopPayType(detailReport);

        if (isEmpty(payTypeList)) {
            return new ArrayList<>();
        }

        return orderList.stream().filter(order -> {
            //过滤
            if (detailReport == null) {
                //默认全部显示
                return true;
            } else {
                //开始过滤数据，支付方式，订单类型之间是
                return orderTypeList.contains(getInt(order.getOrderType())) && payTypeList.contains(getInt(order.getPayType()));
            }
        }).collect(Collectors.toList());
    }

    /**
     * 获取分店的支付类型
     *
     * @param detailReport
     * @return
     */
    private List<Integer> getShopPayType(DetailReport detailReport) {
        List<Integer> payTypeList = detailReport.getPayTypeList();

        if (isEmpty(payTypeList)) {
            try {
                List<PayType> payTypeListCache = payTypeService.findPayTypeListCache_Stripe(detailReport.getShopId());
                payTypeList = payTypeListCache.stream().map(payType -> payType.getType()).collect(Collectors.toList());
            } catch (Exception e) {
                logger.error("e", e);
            }
        }

        return payTypeList;
    }

    /**
     * 添加详情报告
     *
     * @param zh
     * @return
     */
    private PrinterLine addDetailReportTitle(Boolean zh) {
        StringBuffer sb = new StringBuffer();
        sb.append(printerClient.appendCenter(printerClient.appendDouble(config.close_report_detail_report_title(zh))));
        return printerClient.newLine(sb.toString());
    }

    /**
     * 添加详情报告小标题
     *
     * @param zh
     * @return
     */
    private PrinterLine addDetailReportSubTitle(Boolean zh, boolean canShowTipsTitle) {
        if (canShowTipsTitle) {
            StringBuffer sb = new StringBuffer();
            //单号
            sb.append(printerClient.centerLength(config.close_report_order_number_title(zh), LINE_LENGTH / 4));
            //支付方式
            sb.append(printerClient.centerLength(config.close_report_pay_type_title(zh), LINE_LENGTH / 4));
            //金额
            sb.append(printerClient.centerLength(config.close_report_sales_title(zh), LINE_LENGTH / 4));

            //小费
            sb.append(printerClient.centerLength(config.close_tips_fee(zh), LINE_LENGTH / 4));
            return printerClient.newLine(sb.toString());
        } else {
            StringBuffer sb = new StringBuffer();
            //单号
            sb.append(printerClient.centerLength(config.close_report_order_number_title(zh), LINE_LENGTH / 4));
            //支付方式
            sb.append(printerClient.centerLength(config.close_report_pay_type_title(zh), LINE_LENGTH / 2));
            //金额
            sb.append(printerClient.centerLength(config.close_report_sales_title(zh), LINE_LENGTH / 4));
            return printerClient.newLine(sb.toString());
        }
    }

    /**
     * 添加详情报告小标题
     *
     * @param zh
     * @return
     */
    private List<PrinterLine> addDetailReportList(Boolean zh, List<Order> orderList, boolean canShowTipsTitle) {
        return orderList.stream().map(order -> {
            if (canShowTipsTitle) {
                StringBuffer sb = new StringBuffer();

                StringBuilder orderNoSb = new StringBuilder();
                orderNoSb.append(order.getOrderNo());

                if (order.getSubOrderId() != null) {
                    orderNoSb.append("-");
                    orderNoSb.append(order.getSubOrderId());
                }

                //失效订单
                if (getBoolean(order.getExpiredOrder())) {
                    orderNoSb.append(config.expire_order_label(zh));
                }

                //单号
                sb.append(printerClient.centerLength(orderNoSb.toString(), LINE_LENGTH / 4));
                //支付方式
                sb.append(printerClient.centerLength(orderService.getOrderPayType(order, zh), LINE_LENGTH / 4));
                //金额
                //小计 + 税
                sb.append(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(CloseReportService.getInstance().getDetailCash(order))), LINE_LENGTH / 4));

                //添加小费
                sb.append(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(showMoneyDouble(showMoneyDouble(order.getTipsFee()) + showMoneyDouble(order.getServiceFee())))), LINE_LENGTH / 4));

                return printerClient.newLine(sb.toString());

            } else {
                StringBuffer sb = new StringBuffer();

                StringBuilder orderNoSb = new StringBuilder();
                orderNoSb.append(order.getOrderNo());

                if (order.getSubOrderId() != null) {
                    orderNoSb.append("-");
                    orderNoSb.append(order.getSubOrderId());
                }

                //失效订单
                if (getBoolean(order.getExpiredOrder())) {
                    orderNoSb.append(config.expire_order_label(zh));
                }

                //单号
                sb.append(printerClient.centerLength(orderNoSb.toString(), LINE_LENGTH / 4));
                //支付方式
                sb.append(printerClient.centerLength(orderService.getOrderPayType(order, zh), LINE_LENGTH / 2));
                //金额
                sb.append(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(CloseReportService.getInstance().getDetailCash(order))), LINE_LENGTH / 4));

                return printerClient.newLine(sb.toString());
            }
        }).collect(Collectors.toList());
    }

    /**
     * 添加详细报告里面的总的记录
     *
     * @param orderList
     * @param canShowTipsTitle
     * @return
     */
    private PrinterLine addDetailReportTotal(List<Order> orderList, boolean canShowTipsTitle) {
        if (canShowTipsTitle) {
            StringBuffer sb = new StringBuffer();
            //添加单号
            sb.append(printerClient.centerLength(orderList.size(), LINE_LENGTH / 4));
            //添加空格
            sb.append(printerClient.generateSpace(LINE_LENGTH / 4));
            //添加金额
            double sumSales = orderList.stream().mapToDouble(order -> CloseReportService.getInstance().getDetailCash(order)).sum();
            sb.append(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(showDouble(sumSales))), LINE_LENGTH / 4));

            //添加空格
            sb.append(printerClient.generateSpace(LINE_LENGTH / 4));
            return printerClient.newLine(sb.toString());
        } else {
            StringBuffer sb = new StringBuffer();
            //添加单号
            sb.append(printerClient.centerLength(orderList.size(), LINE_LENGTH / 4));
            //添加空格
            sb.append(printerClient.generateSpace(LINE_LENGTH / 2));
            //添加金额
            double sumSales = orderList.stream().mapToDouble(order -> CloseReportService.getInstance().getDetailCash(order)).sum();
            sb.append(printerClient.centerLength(BigDecimalUtil.format(BigDecimal.valueOf(showDouble(sumSales))), LINE_LENGTH / 4));

            return printerClient.newLine(sb.toString());
        }
    }

    /**
     * 添加外卖平台订单数量
     *
     * @param zh
     * @param shopId
     * @return
     */
    private PrinterLine addTakeOutPlatOrderNumber(Boolean zh, Long shopId) throws Exception {
        StringBuffer sb = new StringBuffer();
        //添加标题
        sb.append(printerClient.appendSeparator(config.close_report_take_out_plat_order_number(zh), LINE_LENGTH / 4 * 3, "-"));
        //添加订单量
        ReportService reportService = ReportService.getInstance();
        int platOrderNumber = reportService.countPlatOrderNumber(shopId);

        String platOrderNumberString = null;
        if (zh == null || zh) {
            platOrderNumberString = platOrderNumber + "單";
        } else {
            platOrderNumberString = platOrderNumber + " Checks";
        }

        sb.append(platOrderNumberString);

        return printerClient.newLine(sb.toString());
    }
}
